/**************************************************************************
* @ file    : imi_defs.h
* @ author  : yang yang
* @ version : 0.9
* @ date    : 2017.05.15
* @ brief   : imi库常用定义
*
* @Copyright (c) 2016  chuangmi inc.
***************************************************************************/
 
#ifndef __IMI_DEFS_H__
#define __IMI_DEFS_H__

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h> // need for: strdup, strlen

#include "imi_errno.h"

// min，max宏
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif // !MAX

#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif // !MIN

// 字节对齐宏:

// 获取v按n字节对齐的最小值
#define ALIGN_AHEAD(v, N) ((v) & (~((N) - 1)))

// 获取v按N字节对齐的大值
#define ALIGN_BACK(v, N) (((v) + (N) - 1) & (~((N) - 1)))



// bool
typedef int IMI_BOOL;

#ifndef    FALSE
#define    FALSE    (0)
#endif

#ifndef    TRUE
#define    TRUE    (!FALSE)
#endif

#define TRUE_STR  "true"
#define FALSE_STR "false"

#ifdef DEBUG

#define DBG(...) {printf("%s:%d ", __FILE__, __LINE__);  printf(__VA_ARGS__);}
#define WARN(...) {printf("%s:%d ", __FILE__, __LINE__);  printf(__VA_ARGS__);}
#define ERR(...) {fprintf(stderr, "%s:%d ", __FILE__, __LINE__);  fprintf(stderr, ##__VA_ARGS__) ;}
#define IMI_CHECK(__cond, __normal_format, __err_format, ...) if((__cond)) { printf(__normal_format, ##__VA_ARGS__);} else { printf(__err_format, ##__VA_ARGS__);}
#define IMI_ASSERT(__cond, __format, ...) if(!(__cond)) {printf(__format, ##__VA_ARGS__);}
#define DUMP_HEX(__label, __data, __len)                                       \
  {                                                                            \
    printf("%s: ", __label);                                                   \
    int __i;                                                                   \
    for (__i = 0; __i < __len; __i++) {                                        \
      printf("%02x", (unsigned char)(((char*)(__data))[__i]));                 \
    }                                                                          \
    printf("\n");                                                              \
  }

#else

#define DBG(...)
#define WARN(...)
#define ERR(...) fprintf(stderr, ##__VA_ARGS__)
#define IMI_CHECK(__cond, __normal_format, __err_format, ...)
#define IMI_ASSERT(...)
#define DUMP_HEX(__label, __data, __len)

#endif

#define timevalGreaterEqual(a, b)                                              \
  ((a.tv_sec > b.tv_sec) || (a.tv_sec == b.tv_sec && a.tv_usec >= b.tv_usec))

//----------------------------------------------------------------------------
//  @brief: 比较函数: 比较函数需实现判断2个给定的元素的大小。
//  @elem1: 需要比较的第一个元素
//  @elem2: 需要比较的第二个元素
//  return: elem1 > elem2 大于0
//          elem2 = elem2 等于0
//          elem1 < elem2 小于0
//----------------------------------------------------------------------------
typedef int (*func_imi_comparer)(const void *elem1, const void *elem2);

//----------------------------------------------------------------------------
//  比较函数:   比较函数需判断某个数组中的元素，是否满足检索的条件.
//              检索时会为每一个元素调用该函数
//  @arrayElem: 数组中的元素
//  @data:      检索的data
//  return:     满足检索条件返回0，否则返回非0
//----------------------------------------------------------------------------
typedef int (*func_imi_matcher)(const void *element, const void *data);

//----------------------------------------------------------------------------
//  通用处理函数函数: 用于一般的线程调用，线程池调用等等
//
// @param:      需要送入的参数
// @return:     处理完成的结果
//----------------------------------------------------------------------------
typedef void* (*func_imi_handler)(void* param, void* userdata);

//----------------------------------------------------------------------------
// 通用回调函数: 用于一般的回调场景
//
// @data:       回调函数的结果
// @userdata:   设置回调时，用户设置的userdata。在回调时会带回，用于区分回调
// @返回值：    回调时可以不使用
//----------------------------------------------------------------------------
typedef void* (*func_imi_callback)(void* data, void* userdata);


//----------------------------------------------------------------------------
// hash函数定义: 用于一般的回调场景
//
// @key:        需要hash的key
// @return:     hash后的值
//----------------------------------------------------------------------------
typedef unsigned (*func_imi_hash)(const void *key);


//-------------------------------------------------------------------------------------
//  key复制函数定义
//-------------------------------------------------------------------------------------
typedef void* (*func_key_duplicate)(const void* key);

//-------------------------------------------------------------------------------------
//  key释放函数
//-------------------------------------------------------------------------------------
typedef void(*func_key_release)(void* key);


//-------------------------------------------------------------------------------------
// value释放函数
// @value   需要释放的value
//-------------------------------------------------------------------------------------
typedef void(*func_value_release)(void* value);

#ifdef MEMWATCH

void* mwMalloc(size_t, const char*, int);
void* mwCalloc(size_t, size_t, const char*, int);
void* mwRealloc(void *, size_t, const char*, int);
char* mwStrdup(const char *, const char*, int);
void  mwFree(void*, const char*, int);


#define _IMI_NEW(struct_type, n_structs, file, line) \
        ((struct_type *) mwMalloc((n_structs) * sizeof (struct_type), file, line))

#define _IMI_MALLOC(size, file, line) mwMalloc(size, file, line)

#define _IMI_CALLOC(n, size, file, line) mwCalloc(n, size, file, line)

#define _IMI_REALLOC(ptr, size, file, line) mwRealloc(ptr, size, file, line)

#define _IMI_STRDUP(str, file, line) mwStrdup(str, file, line)

#define _IMI_FREE(ptr, file, line) mwFree(ptr, file, line)

#define _IMI_FREE0(ptr, file, line) { mwFree(ptr, file, line); ptr = NULL; }

#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
#define _IMI_NEW0(struct_type, n_structs, file, line)   \
        ({                              \
            int size = (n_structs) * sizeof (struct_type);                          \
            void* ptr = mwMalloc(size, file, line); if(ptr) memset(ptr, 0, size);   \
            (struct_type*)ptr;                             \
        })
#else
void* __imi_mw_malloc0(size_t size, const char* file, int line);
#define _IMI_NEW0(struct_type, n_structs, file, line)   \
        ((struct_type *) __imi_mw_malloc0((n_structs) * sizeof (struct_type), file, line))
#endif

#else //!MEMWATCH

char *imi_clone_string(const char* value);

#define _IMI_NEW(struct_type, n_structs, file, line)   \
        ((struct_type *) malloc((n_structs) * sizeof (struct_type)))

#define _IMI_MALLOC(size, file, line) malloc(size)

#define _IMI_CALLOC(n, size, file, line) calloc(n, size)

#define _IMI_REALLOC(ptr, size, file, line) realloc(ptr, size)

#define _IMI_STRDUP(str, file, line) imi_clone_string(str)

#define _IMI_FREE(ptr, file, line) free(ptr)

#define _IMI_FREE0(ptr, file, line) { free(ptr); ptr = NULL; }

#if defined  (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
#define _IMI_NEW0(struct_type, n_structs, file, line)               \
        ({                                                          \
            int size = (n_structs) * sizeof (struct_type);          \
            void* ptr = malloc(size); if(ptr) memset(ptr, 0, size); \
            (struct_type*)ptr;                                      \
        })

#define _IMI_MALLOC0(size, file, line)                              \
        ({                                                          \
            void* ptr = malloc(size); if(ptr) memset(ptr, 0, size); \
        })
#else

void* __imi_malloc0(size_t size);

#define _IMI_NEW0(struct_type, n_structs, file, line)   \
        ((struct_type *) __imi_malloc0((n_structs) * sizeof (struct_type)))

#define _IMI_MALLOC0(size, file, line) __imi_malloc0(size)

#endif

#endif //MEMWATCH


#define imi_new(struct_type, n_structs)    _IMI_NEW(struct_type, n_structs, __FILE__, __LINE__)

#define imi_new0(struct_type, n_structs) _IMI_NEW0(struct_type, n_structs, __FILE__, __LINE__)

#define imi_malloc(size) _IMI_MALLOC(size, __FILE__, __LINE__)

#define imi_malloc0(size) _IMI_MALLOC0(size, __FILE__, __LINE__)

#define imi_calloc(n, size) _IMI_CALLOC(n, size, __FILE__, __LINE__)

#define imi_realloc(ptr, size) _IMI_REALLOC(ptr, size, __FILE__, __LINE__)

#define imi_strdup(str) _IMI_STRDUP(str, __FILE__,__LINE__)

#define imi_free(ptr) _IMI_FREE(ptr, __FILE__,__LINE__)

#define imi_free0(ptr) _IMI_FREE0(ptr, __FILE__,__LINE__)

#define imi_strlen(str) (str ? strlen(str) : 0)

#define throw_not_implement_exception abort

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

#endif // __IMI_DEFS_H__
